package com.tos.second.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.tos.second.common.Result.PageResult;
import com.tos.second.common.basecontext.BaseContext;
import com.tos.second.common.constant.MessageConstant;
import com.tos.second.common.exception.BaseException;
import com.tos.second.common.exception.BuyException;
import com.tos.second.dto.*;
import com.tos.second.entity.*;
import com.tos.second.mapper.GoodsMapper;
import com.tos.second.mapper.OrdersMapper;
import com.tos.second.mapper.ShoppingCartMapper;
import com.tos.second.mapper.UserMapper;
import com.tos.second.service.CategoryService;
import com.tos.second.service.GoodsService;
import com.tos.second.service.OrdersService;
import com.tos.second.service.UserService;
import com.tos.second.utils.MailMsg;
import com.tos.second.utils.MailUtils;
import com.tos.second.vo.GoodsGetVo;
import com.tos.second.webSocketServer.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class GoodsServiceImpl extends ServiceImpl<GoodsMapper, Goods> implements GoodsService {


    @Autowired
    private  GoodsMapper goodsMapper;
    @Autowired
    private  CategoryService categoryService;
    @Autowired
    private  UserService userService;
    @Autowired
    private  OrdersMapper ordersMapper;
    @Autowired
    private  UserMapper userMapper;
    @Autowired
    private  OrdersService ordersService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private  ShoppingCartMapper shoppingCartMapper;
    @Autowired
    private WebSocketServer webSocketServer;
    @Autowired
    private MailMsg mailMsg;



    /**
     * 分页查询分类商品
     *
     * @param categoryId
     * @return
     */
    @Override
     public PageResult getPage(Long categoryId , Integer pageNum, Integer pageSize) {


        //获得分类id判断是否为空
        if (categoryId == null){
            throw new BaseException("分类id不能为空");
        }

        //先在redis中查询
        String redisKey = "category_goods:" + categoryId + ":page" + pageNum + ":size" + pageSize;

        // 尝试从 Redis 中获取数据
        PageResult cachedResult = (PageResult) redisTemplate.opsForValue().get(redisKey);
        if (cachedResult != null) {
            // 如果缓存存在，直接返回结果
            return cachedResult;
        }

        // 使用 PageHelper 分页
        PageHelper.startPage(pageNum, pageSize);
        Page<Goods> goodsPage = goodsMapper.pageQuery(categoryId);

        // 封装分页结果
        PageResult result = new PageResult(goodsPage.getTotal(), goodsPage.getResult());

        // 将结果缓存到 Redis 中
        redisTemplate.opsForValue().set(redisKey, result,1,TimeUnit.HOURS);
        return result;
//        PageHelper.startPage(pageNum, pageSize);
//        Page<Goods> goodsPage = goodsMapper.pageQuery(categoryId);
//
////        //查询商品
////        LambdaQueryWrapper<Goods> queryWrapper = new LambdaQueryWrapper<>();
////        queryWrapper.eq(Goods::getCategoryId, categoryId);
////        queryWrapper.orderByDesc(Goods::getCreateTime);
//
//        return new PageResult(goodsPage.getTotal(), goodsPage.getResult());
    }

    /**
     * 添加商品
     *
     * @param goodsAddDto
     */
    @Override
    public void addGoods(GoodsAddDto goodsAddDto) {
        Goods goods = new Goods();
        //赋值属性，自动填充
        if (goodsAddDto.getPrice() == null || goodsAddDto.getPrice().compareTo(BigDecimal.ZERO) < 0){
            throw new BaseException(MessageConstant.PRICE_ERROR);
        }
        //价格过高
        if (goodsAddDto.getPrice() .compareTo(new BigDecimal("99999")) > 0){
            throw new BaseException(MessageConstant.PRICE_TOO_HIGH);
        }

        //添加商品
        if (BaseContext.getCurrentId() == null) {
            throw new BaseException(MessageConstant.USER_NOT_LOGIN);
        }
        // 删除redis中的newGoodsCache，goodsCache，user_goods,home,category_goods,rec_goods
        deleteRedisCaches();
        // 赋值
        BeanUtils.copyProperties(goodsAddDto, goods);
        //根据分类id查询分类信息
        Category category = categoryService.getById(goodsAddDto.getCategoryId());
        if (category == null){
            throw new BaseException(MessageConstant.CATEGORY_NOT_EXIT);
        }
        goods.setCategoryName(category.getName());
        //根据上架者id查询用户信息
        User user = userService.getById(BaseContext.getCurrentId());
        goods.setSellerName(user.getName());
        goods.setSellerPhone(user.getPhone());
//        goodsMapper.saveUser(goods);

        save(goods);
//        log.info("添加成功：{}",goods);
        //向es中添加数据
//        GoodsDoc goodsDoc = new GoodsDoc();
//        BeanUtils.copyProperties(goods, goodsDoc);
//        IndexRequest request = new IndexRequest("goods").id(goodsDoc.getId().toString());
//        request.source(JSONUtil.toJsonStr(goodsDoc), XContentType.JSON);
//        try {
//            client.index(request, RequestOptions.DEFAULT);
//        } catch (IOException e) {
//            throw new BaseException(MessageConstant.ES_ERROR);
//        }
    }

    /**
     * 根据id查询商品
     *
     * @param id
     * @return
     */
    @Override
    public GoodsGetVo getGoodsById(Long id) {
        if (id == null) {
            throw new BaseException("id不能为空");
        }
        //如果商品状态不是1查询不到
        if (getById(id) == null || getById(id).getStatus() != 1) {
            return null;
        }
        //数据库中查询商品信息
//        Goods goods = getById(id);
        Goods goods = goodsMapper.getGoodsById(id);
        if (goods == null){
            throw new BaseException(MessageConstant.GOODS_NOT_EXIT);
        }
        GoodsGetVo goodsGetVo = new GoodsGetVo();

        //将商品信息复制到vo上
        BeanUtils.copyProperties(goods, goodsGetVo);
        User user = userMapper.getById(goods.getCreateUser());
        goodsGetVo.setUserImage(user.getImage());
        //根据商品id查询用户图片
        return goodsGetVo;
    }

    /**
     * 购买商品
     *
     * @param id
     * @param goodsBuyDto
     */
    @Override
    @Transactional
    public String buy(Long id, GoodsBuyDto goodsBuyDto)  {
        String number = null;
        //如果订单状态为0
        if (goodsBuyDto != null && goodsBuyDto.getStatus() != null && goodsBuyDto.getStatus() == 0) {
            //根据商品id获取商品
//        Goods goods = getById(id);
            Goods goods = goodsMapper.getGoodsById(id);
            //判断是否有商品
            if (goods == null || goods.getStatus() != 1) {
                throw new BuyException(MessageConstant.GOODS_NOT_EXIT);
            }
            //获取商品中的卖家
            Long sellerId = goods.getCreateUser();
            //查询数据库
            User sellerUser = userMapper.getById(sellerId);
            //获得买家id，即当前登录id
            Long buyerId = BaseContext.getCurrentId();
            if (buyerId == null){
                throw new BuyException(MessageConstant.USER_NOT_LOGIN);
            }
            //判断是否为同一人
            if (sellerId.equals(buyerId)) {
                throw new BuyException(MessageConstant.CAN_NOT_BUY_YOURSELF);
            }
            //如果不是同一人，获得买家数据库
            User buyerUser = userMapper.getById(buyerId);
            //获取商品价格和用户余额
            BigDecimal price = goods.getPrice();
            BigDecimal balance = buyerUser.getBalance();

            //判断余额是否足够
            if (balance.compareTo(price) < 0) {
                throw new BuyException(MessageConstant.BALANCE_NOT_ENOUGH);
            }
            deleteRedisCaches();

            // 生成订单号
            String number0 = String.valueOf(System.currentTimeMillis());
            Orders orders = Orders.builder()
                    .amount(price)
                    .goodsId(id)
                    .buyerName(buyerUser.getName())
                    .sellerName(sellerUser.getName())
                    .orderTime(LocalDateTime.now())
                    .description(goodsBuyDto.getDescription())
                    .number(number0)
                    .buyerId(buyerId)
                    .sellerId(sellerId)
                    .categoryId(goods.getCategoryId())
                    .status(goodsBuyDto.getStatus()) // 设置订单状态
                    .build();
            ordersMapper.saveOrder(orders);
            String timeoutKey = "order:timeout:" + number0;
            redisTemplate.opsForValue().set(timeoutKey, number0, 15, TimeUnit.MINUTES);
            //将number0赋值到number
            number = number0;
            //删除购物车中的数据
            shoppingCartMapper.removeById(id, buyerId);
//            // 查询所有符合条件的订单：goods_id 和 buyer_id 都匹配
//            List<Orders> orderList = ordersService.list(
//                    new QueryWrapper<Orders>()
//                            .eq("goods_id", id) // 商品 ID 条件
//                            .eq("buyer_id", buyerId) // 买家 ID 条件
//            );
//
//            // 如果存在相关订单，则删除相关订单
//            if (!orderList.isEmpty()) {
//                ordersService.remove(
//                        new QueryWrapper<Orders>()
//                                .eq("goods_id", id) // 商品 ID 匹配
//                                .eq("buyer_id", buyerId) // 买家 ID 匹配
//                );
//            }

        }


        //如果订单状态为1，更新余额
        if (goodsBuyDto != null && goodsBuyDto.getStatus() != null && goodsBuyDto.getStatus() == 1) {
            //获取订单号
            String number1 = goodsBuyDto.getNumber();
            //获取买家id
            Long buyerId = BaseContext.getCurrentId();
            User buyerUser = userMapper.getById(buyerId);
            //通过订单号查询卖家
            Long sellerId = ordersMapper.getSellerIdByNumber(number1);
            User sellerUser = userMapper.getById(sellerId);
            //获取商品价格
            BigDecimal balance = buyerUser.getBalance();
            //根据订单号查询商品id
            Long goodsId = ordersMapper.getGoodsId(number1);
            Goods goods = goodsMapper.getGoodsById(goodsId);
            //判断是否有商品
            if (goods == null || goods.getStatus() != 1) {
                throw new BuyException(MessageConstant.GOODS_NOT_EXIT);
            }
            BigDecimal price = goods.getPrice();

            //根据订单号修改订单状态
            ordersMapper.updateStatus(number1, 1);
            //买家余额减少
            buyerUser.setBalance(balance.subtract(price));
            goods.setStatus(2);
            updateById(goods);
            //卖家余额增加
            sellerUser.setBalance(sellerUser.getBalance().add(price));
//更新数据库中的余额
//        userService.updateById(buyerUser);
            userMapper.updateUser(buyerUser);
            //更新数据库中的余额
////        userService.updateById(sellerUser);
            userMapper.updateUser(sellerUser);
            //删除未支付的订单
            //ordersMapper.remove(buyerId);
            //根据订单号查询订单
            Orders ordersDB = ordersMapper.getOrderByNumber(number1);
            //将ChatMessage类型的json发送到卖家
            ChatMessage json = new ChatMessage();
            json.setMessage(goods.getName() + "已售出");
            // 使用聊天WebSocket推送消息给卖家
            try {
                com.tos.second.common.handler.ChatWebSocketHandler.sendMessageToUser(sellerId, json);
            } catch (Exception e) {
                log.error("发送WebSocket消息失败: {}", e.getMessage());
            }
            
            //商品名
            String goodsName = goods.getName();
            //发送邮件给卖家
            //mailMsg.mailException("2935149173@qq.com","数据库操作失败，请管理员及时检查");
            try {
                mailMsg.mailException(sellerUser.getEmail(), "您的商品"+ goodsName +"已售出");
            } catch (Exception e) {
                log.error("发送邮件失败: {}", e.getMessage());
            }
        }
        //如果订单状态为2
        if (goodsBuyDto.getStatus() == 2) {
            String number2 = goodsBuyDto.getNumber();
            ordersMapper.updateStatus(number2, 2);
        }

        deleteRedisCaches();//删除redis缓存
        return number;
        //buyerUser.setBalance(balance.subtract(price));
        //更新数据库中的商品status为2
//        goods.setStatus(2);
//        updateById(goods);
//        //卖家余额增加
//        sellerUser.setBalance(sellerUser.getBalance().add(price));
////更新数据库中的余额
////        userService.updateById(buyerUser);
//        userMapper.updateUser(buyerUser);
//        //更新数据库中的余额
////        userService.updateById(sellerUser);
//        userMapper.updateUser(sellerUser);


        //deleteRedisCaches();//删除redis缓存
    }
    /**
     * 根据id修改商品状态
     * @param status
     * @param id
     */
    @Override
    public void startOrStopById(Integer status, Long id) {

        //根据id查询商品
//        Goods goods = getById(id);
        Goods goods = goodsMapper.getGoodsById(id);
        //判断商品是否存在
        if (goods == null) {
            throw new BaseException(MessageConstant.GOODS_NOT_EXIT);
        }
        //判断商品状态
        if (goods.getStatus() == 2) {
            throw new BaseException(MessageConstant.ALREADY_BUY);
        }
        //删除redis
        deleteRedisCaches();
        //修改商品状态
        goods.setStatus(status);
        //更新数据库
//        updateById(goods);
        goodsMapper.updateGoods(goods);
    }

    @Override
    public List<Goods> getNewGoods() {
        return goodsMapper.getNewGoods();
    }

    //获取当前用户的商品
    @Override
    public List<Goods> getMyGoods() {
        // 获取当前登录用户的ID
        Long currentId = BaseContext.getCurrentId();
        if (currentId == null) {
            throw new IllegalStateException("用户未登录");
        }

        // 检查 Redis 中是否存在该用户的商品数据
        String redisKey = "user_goods:" + currentId;
        List<Goods> goodsList = (List<Goods>) redisTemplate.opsForValue().get(redisKey);

        if (goodsList == null || goodsList.isEmpty()) {
            // 如果 Redis 中没有数据，则从数据库中查询
            goodsList = goodsMapper.getMyGoods(currentId);

            // 将查询结果缓存到 Redis
            if (goodsList != null && !goodsList.isEmpty()) {
                redisTemplate.opsForValue().set(redisKey, goodsList,1,TimeUnit.HOURS); // 设置缓存有效期为10分钟
            }
        }

        // 返回用户的商品数据
        return goodsList;
    }


    /**
     * 根据id修改商品信息
     * @param goodsChangeDto
     */
    @Override
    public void changeGoodsMsg(GoodsChangeDto goodsChangeDto) {
        //获得当前登录用户id
        Long currentId = BaseContext.getCurrentId();

        //判断用户是否登录
        if (currentId == null){
            throw new BaseException(MessageConstant.NOT_LOGIN);
        }
        //获得商品id
        Long goodsChangeDtoId = goodsChangeDto.getId();
        if (goodsChangeDtoId == null){
            throw new BaseException(MessageConstant.GOODS_NOT_EXIT);
        }
        //根据id查询商品
        Goods goodsById = goodsMapper.getGoodsById(goodsChangeDtoId);
        //查询商品的用户u
        Long createUser = goodsById.getCreateUser();

        //判断当前登录用户是否为商品的创建者
        if (!currentId.equals(createUser)) {
            throw new BaseException(MessageConstant.NOT_AUTHORIZED);
        }
        //更改信息
        Goods goods = new Goods();
        BeanUtils.copyProperties(goodsChangeDto, goods);

        //删除redis缓存
        deleteRedisCaches();
        //更新数据库
        goodsMapper.updateGoods(goods);

    }

    //搜索商品
    @Override
    public PageResult getGoodsByName(GoodsSearchDto goodsSearchDto) {
        // 校验输入参数是否为 null
        if (goodsSearchDto == null) {
            throw new BaseException("查询参数不能为空");
        }
        
        // 验证排序字段，防止SQL注入
        String sortField = goodsSearchDto.getSortField();
        String sortOrder = goodsSearchDto.getSortOrder();
        if (sortField != null) {
            // 只允许特定的字段进行排序
            Set<String> allowedFields = Set.of("id", "name", "price", "create_time", "update_time");
            if (!allowedFields.contains(sortField)) {
                sortField = "update_time"; // 默认排序字段
            }
        }
        
        if (sortOrder != null) {
            // 只允许ASC或DESC排序
            if (!"ASC".equalsIgnoreCase(sortOrder) && !"DESC".equalsIgnoreCase(sortOrder)) {
                sortOrder = "DESC"; // 默认排序方式
            }
        }
        
        //根据goodsSearchDto中的商品名查询商品id
        //如果商品状态不是1查询不到
        // 从搜索 DTO 中提取名称和分类 ID
        String name = goodsSearchDto.getName();
        Long categoryId = goodsSearchDto.getCategoryId();
        Integer pageNum = goodsSearchDto.getPageNum();
        Integer pageSize = goodsSearchDto.getPageSize();

        // 构建 Redis 缓存的 Key，区分不同条件组合
        String redisKey = "search_goods:" +
                (name != null ? "name:" + name : "name:ALL") +
                (categoryId != null ? ":category:" + categoryId : ":category:ALL") +
                ":page:" + pageNum + ":size:" + pageSize;

        // 尝试从 Redis 中获取缓存结果
//        PageResult cachedResult = (PageResult) redisTemplate.opsForValue().get(redisKey);
//        if (cachedResult != null) {
//            return cachedResult;
//        }

        // 使用分页插件查询
        PageHelper.startPage(pageNum, pageSize);
        List<Goods> goodsPage = goodsMapper.getGoodsByName(goodsSearchDto);
        PageInfo<Goods> pageInfo = new PageInfo<>(goodsPage);
        log.info("pageInfo:{}", pageInfo);
        // 封装分页结果
        PageResult result = new PageResult(pageInfo.getTotal(), pageInfo.getList());


        // 将结果缓存到 Redis，设置有效期（如 10 分钟）
        //redisTemplate.opsForValue().set(redisKey, result, 1, TimeUnit.HOURS);

        return result;
    }



    //获取推荐商品
    @Override
    public List<Goods> getRecGoods() {
        // 获取当前登录用户ID
        Long currentId = BaseContext.getCurrentId();
        if (currentId == null) {
            throw new BaseException("用户未登录");
        }

        // 定义 Redis 缓存 Key
        String redisKey = "recGoods:" + currentId;

        // 尝试从 Redis 中获取推荐商品
        List<Goods> cachedGoods = (List<Goods>) redisTemplate.opsForValue().get(redisKey);
        if (cachedGoods != null && !cachedGoods.isEmpty()) {
            return cachedGoods;
        }

        // 获取用户的历史订单
        LambdaQueryWrapper<Orders> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Orders::getBuyerId, currentId);
        List<Orders> ordersList = ordersService.list(queryWrapper);

        if (ordersList.isEmpty()) {
            List<Goods> newGoods = goodsMapper.getNewGoods();
            redisTemplate.opsForValue().set(redisKey, newGoods,1, TimeUnit.HOURS);
            // 如果用户没有历史订单，直接返回最新商品
            return newGoods;
        }

        // 从订单中提取分类ID
        List<Long> categoryIds = ordersList.stream()
                .map(Orders::getCategoryId)
                .filter(Objects::nonNull)
                .toList();

        if (categoryIds.isEmpty()) {
            // 如果没有分类ID，返回最新商品
            return goodsMapper.getNewGoods();
        }

        // 统计分类ID出现次数，并按频率排序，获取最多的两个分类ID
        Map<Long, Long> categoryFrequency = categoryIds.stream()
                .collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));

        List<Long> topTwoCategoryIds = categoryFrequency.entrySet().stream()
                .sorted((e1, e2) -> e2.getValue().compareTo(e1.getValue())) // 按出现频率降序排序
                .limit(2) // 取前两个分类ID
                .map(Map.Entry::getKey)
                .toList();

        // 根据分类ID查询商品
        List<Goods> recommendedGoods = new ArrayList<>();
        for (Long categoryId : topTwoCategoryIds) {
            recommendedGoods.addAll(goodsMapper.getGoodsByCategoryId(categoryId));
        }

        // 如果推荐商品为空，返回最新商品
        if (recommendedGoods.isEmpty()) {
            recommendedGoods = goodsMapper.getNewGoods();
        }

        // 将推荐商品缓存到 Redis，设置有效期（如30分钟）
        redisTemplate.opsForValue().set(redisKey, recommendedGoods,1, TimeUnit.HOURS);

        return recommendedGoods;
    }


    // 获取首页商品
    @Override
    public List<Goods> getHomeList(Long categoryId) {
        // 调用mapper
        return goodsMapper.getGoodsByCategoryIdLimitNine(categoryId);
    }

    /**
     * 删除为id的商品
     * @param id
     */
    @Override
    public void deleteById(Long id) {
        // 查询是否为自己商品
        Long currentId = BaseContext.getCurrentId();
        if (currentId == null){
            throw new BaseException("未登录");
        }
        //根据商品id查询商品
        Goods goods = getById(id);
        if (goods == null) {
            throw new BaseException("商品不存在");
        }
        //取出goods中的创建人
        Long createUser = goods.getCreateUser();
        if (!currentId.equals(createUser)) {
            throw new BaseException(MessageConstant.NOT_AUTHORIZED);
        }
        //校验通过，删除redis
        deleteRedisCaches();
        goodsMapper.deleteById(id);
    }

    @Override
    public List<Goods> listById(Long categoryId) {
        return goodsMapper.getGoodsByCategoryId(categoryId);
    }


    private void deleteRedisCaches() {
        // 定义需要删除的 Redis 缓存键
        List<String> aKeys = Arrays.asList(
                "newGoodsCache",
                "goodsCache",
                "user_goods",
                "home",
                "category_goods",
                "recGoods"
        );


        for (String key : aKeys) {
            Set<String> keys = redisTemplate.keys(key + ":*");
            if (keys != null && !keys.isEmpty()) {
                redisTemplate.delete(keys);
                log.info("删除key成功");
            }
        }
    }


}
